package gbench.sandbox.matrix.img;

import org.junit.jupiter.api.Test;
import java.util.*;
import java.util.function.Function;

import gbench.common.fs.XlsFile;
import gbench.common.fs.XlsFile.DataMatrix;

import static gbench.common.tree.LittleTree.IRecord.*;
import static gbench.commonApp.data.DataMatrixApp.*;
import static gbench.sandbox.matrix.img.util.ImagePlot.*;
import static gbench.sandbox.matrix.img.util.ImageOps.*;
import static java.lang.Math.*;

/**
 * 把一张图片旋转45度
 * @author gbench
 *
 */
public class JunitRotate {
    
    /**
     * 打印图片
     */
    @Test
    public void foo() {
        final var jpgpath = "C:/Users/Administrator/Pictures/pics/拿破仑.jpg";
        final var rgbinfo = img2rgbinfo(jpgpath); // 图像的像素数据
        final var xyrgbs = rgbinfo2xyrgbs(rgbinfo);// 图像的色彩空间
        final var height = rgbinfo.i4("height");// 图像垂直高度
        final var width = rgbinfo.i4("width");// 推向水平宽度
        final var rgbs = new int[width][height][3];// 颜色矩阵
        
        // -------------------------------------------------------------
        // 图片灰化
        // -------------------------------------------------------------
        
        // 颜色加工处理：制作灰色图片
        xyrgbs.forEach(xyrgb->{// 颜色向量{x,y,r,g,b}
            final var x = xyrgb[0]; // 水平坐标
            final var y = xyrgb[1]; // 垂直坐标
            final var blue = xyrgb[2];// 提取蓝色分量
            
            // r,g,b通道 统一用蓝色分量写入。
            rgbs[x][y][0] = blue; // 红色通道
            rgbs[x][y][1] = blue; // 绿色通道
            rgbs[x][y][2] = blue; // 蓝色通道
        });// forEach：制作灰色图片
        
        // 黑白图片输出
        jpgwrite(rgbs, "C:/Users/Administrator/Pictures/pics/gray.jpg");
        
        // -------------------------------------------------------------
        // 图片旋转
        // -------------------------------------------------------------
        
        final var mx = DataMatrix.of3(box(xyrgbs)).corece(Double.class);// 转换成 rgbcolors
        final var theta = PI/4;// 旋转的角度
        final var rotatemx = DSQB(5).get( // 旋转矩阵:补充图像数据
            
            //列向量的变换分块矩阵:坐标旋转
            cos(theta), -sin(theta),     0d,0d,0d,
            sin(theta), cos(theta),      0d,0d,0d,
            
            // 列向量的保留分块矩阵:颜色数据矩阵
            0d,         0d,              1d,0d,0d,
            0d,         0d,              0d,1d,0d,
            0d,         0d,              0d,0d,1d
            
        );// 随机生成一个矩阵
        
        final var xyrgbs_rotated = rotatemx.mmult(mx).transpose() // 每行一个色彩向量(xy,rgb)
            .lrows(e->Arrays.stream(e).mapToInt(Number::intValue).toArray());// 矩阵旋转 形成 [xyrgb]
        final var ranges = new int[] { // 边界值
            0,0, // 水平 x 方向的 最小值，最大值
            0,0  // 垂直y 方向的 最小值，最大值
        };// 图片的范围边界
        
        // 边界侦测
        xyrgbs_rotated.forEach(aa->{ // 寻找图片边界
            // 水平x方向 边界内检测
            if(ranges[0]>aa[0])ranges[0]=aa[0];// 最小值
            if(ranges[1]<aa[0])ranges[1]=aa[0];// 最大值
            
            // 垂直y方向 边界内检测
            if(ranges[2]>aa[1])ranges[2]=aa[1];// 最小值
            if(ranges[3]<aa[1])ranges[3]=aa[1];// 最大值
        });// 边界侦测
        
        // 矫正偏移
        xyrgbs_rotated.forEach(aa->{ // 数据调整
            aa[0]-=ranges[0];// 偏移到 x方向最小值的点
            aa[1]-=ranges[2];// 偏移到 y方向最小值的点
        });
        // 由于ranges[1],ranges[3]边界点为inclusive点，所以索引间隔转换成距离长度的时候需要 +1 
        final var bimg = xyrgbs2bimg( ranges[1]-ranges[0]+1, ranges[3]-ranges[2]+1, xyrgbs_rotated);// 生成内存图片
        
        // 结果输出
        imgwrite(bimg, "C:/Users/Administrator/Pictures/pics/rotated.jpg","jpg");
        System.out.println("图片翻转结束");
    }
    
    @Test
    public void bar() {
        final var theta = PI/4;// 角度
        final var rotatemx = DSQB(5).get( // 旋转矩阵
            
            //列向量的变换分块矩阵:坐标旋转
            cos(theta), -sin(theta),     0d,0d,0d,
            sin(theta), cos(theta),      0d,0d,0d,
            
            // 列向量的保留分块矩阵:颜色数据矩阵
            0d,         0d,              1d,0d,0d,
            0d,         0d,              0d,1d,0d,
            0d,         0d,              0d,0d,1d
            
        );// 随机生成一个矩阵
        System.out.println(rotatemx);
        final var vv = rotatemx.melt( e -> A (// 向量化
            e._1()._1().doubleValue(),// x
            e._1()._2().doubleValue(), // y
            e._2() )
        );
        final var mx = DataMatrix.of3(vv);
        System.out.println(mx);
    }
    
    /**
     * 显示图片
     * 
     * @param args
     */
    public static void main(String args[]) {
        final var size = 500;
        final var mx = SQB(Integer.class, size).get(0);// 生成一个方阵
        final var rand = new Random();// 随机生成器
        final var renderer = (Function<XlsFile.Tuple2<int[], Integer>, int[]>) e -> { // 颜色向量 描绘器 
            final var xy = e._1();// 坐标
            final var red_point = (Function<Integer,int[]>) (p->new int[] {xy[0], xy[1],p,0,0});// 生成点坐标 绘制红点
            return  
                xy[0] > xy[1] // 区域范围表达式
                ? red_point.apply(255) // 绘制红点
                : new int[] {xy[0], xy[1], rand.nextInt(255),rand.nextInt(255),rand.nextInt(255) }; // 背景色
        };
        final var xyrgbs = mx.melt3(renderer);// 绘制颜色向量
        plot(xyrgbs2bimg(size,size, xyrgbs));
    }

}
